package com.dhy.dbCore;

import com.dhy.dbCore.dataSource.DataSourceUtils;
import com.dhy.dbCore.util.BeanUtils;
import lombok.extern.slf4j.Slf4j;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;

/**
 * @author 大忽悠
 * @create 2022/6/6 21:17
 */
@Slf4j
public class JdbcTemplate {
    private final DataSource dataSource;

    public JdbcTemplate(DataSource dataSource) {
        this.dataSource=dataSource;
    }

    public Integer update(String sql){
        log.info("需要执行的sql语句为: {}",sql);
        return execute(new ExecutionCallback<Integer>() {
            @Override
            public Integer execution(Statement st) throws SQLException {
                return st.executeUpdate(sql);
            }
        });
    }

    public Boolean insert(String sql){
        log.info("需要执行的sql语句为: {}",sql);
        return execute(new ExecutionCallback<Boolean>() {
            @Override
            public Boolean execution(Statement st) throws SQLException {
                return st.execute(sql);
            }
        });
    }

    public Boolean delete(String sql){
        log.info("需要执行的sql语句为: {}",sql);
        return execute(new ExecutionCallback<Boolean>() {
            @Override
            public Boolean execution(Statement st) throws SQLException {
                return st.execute(sql);
            }
        });
    }


    public <T> List<T> list(String sql,Class<T> targetClass){
        log.info("需要执行的sql语句为: {}",sql);
          return execute(new ExecutionCallback<List<T>>() {
              @Override
              public List<T> execution(Statement st) throws SQLException {
                  ResultSet resultSet = st.executeQuery(sql);
                  return BeanUtils.autoWiredList(resultSet, targetClass);
              }
          });
    }

    public <T> T queryOne(String sql,Class<T> targetClass){
        log.info("需要执行的sql语句为: {}",sql);
        return list(sql,targetClass).get(0);
    }

    public Boolean execute(String sql){
        log.info("需要执行的sql语句为: {}",sql);
        return execute(new ExecutionCallback<Boolean>() {
            @Override
            public Boolean execution(Statement st) throws SQLException {
                return st.execute(sql);
            }
        });
    }

    /**
     * 通用模板方法
     */
    public <T> T execute(ExecutionCallback<T> callback){
        Connection connection = DataSourceUtils.getConnection(dataSource);
        T res = null;
        Statement statement=null;
        try {
             statement= connection.createStatement();
             res= callback.execution(statement);
        }catch (Exception e){
            log.error("执行出错: ",e);
        }finally {
            close(statement);
        }
        return res;
    }

    private void close(Statement statement) {
        try {
            if(statement!=null){
                statement.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
